マルチブートの仕方(Linux中級編)
Linuxは論理領域にも置いても、第2ハードディスク以降に置いても、起動、また起動後のOSの動作上全く問題ない。制約の多いWindows系OSとの共存時にはこのLinuxの自由度が役に立つ。貴重な基本領域をLinuxのために消費する必要がないからだ。
これらは勿論LinuxというOSの柔軟性に負うところが大きいのだが、現在その標準ローダとなっているLILOの多機能性にも大きく依存している。欠点も非常に多いローダであり、最近はGRUBを標準にしたディストリビューションも出てきているようだが、まだまだLinux標準ブートローダとしての位置は揺らいでいない。だからやはりこのLILOを使いこなさずして、Linuxマルチブートの極めたとはいえないだろう。このLinux中級編のページはすなわちLILOの使いこなすことを目指そう。
さて、LILOを使いこなすにはまずその使い勝手の向上を図る必要があると思うが、その点に関しては「LILOの使い勝手の向上」に譲る。一応このページは後回しでも構いないが、遅かれ早かれ読んでおく必要があると思う。
以下に、以前、実際に私が構築した構成を紹介する。ハードディスクは20GBのものが2つ。ここにWindows系OSは6つ(図には現れていないが、NTLDRからWindows2000がProfessionalとServer、それとWindowsNT4.0を起動)、Linuxは4つのディストリビューションをインストールしてある。開発アプリケーションのテストの関係上、必要最低限のOS群でした。まあ特別OSの数が多い訳ではないが、この構成の中にはマルチブートのテクニック、特にLILOのテクニックがふんだんに利用されている。
実はテストの関係上、ハードディスクAとハードディスクBはしばしばBIOSからみた順序を変更する。ハードディスクAはUltraATA66カードのプライマリーマスターに接続してあり、ハードディスクBはマザーボードのノーマルIDEのプライマリーマスターに接続している。UltraATA66カードはSCSIカードとして認識されるので、BIOSのブートシーケンスで、SCSIを先にしたり、IDEを先にしたりといった変更を行って、ハードディスクの順序を変更する。
メインはハードディスクAで、そこ第1基本領域にインストールしたWindows2000Proが最も利用頻度が高いのだが、他のOSの起動する機会も多く、ハードディスクBを第1ハードディスクにする頻度も高い。そこでハードディスクの順序の如何に関わらず、10個のOSを問題なく、しかも手間無く、起動するための構成を模索した訳で、その結果が上記の構成ということになる。
ざっと起動の流れを説明すると、ハードディスクAのMBRには「フリーツール編」でも説明するMBMというブートローダを置いている。だからハードディスクAを第1ハードディスクにしている時はまずこのMBMが起動する。MBMは基本領域と拡張領域を起動できる * ので、各基本領域とハードディスクAの拡張領域を起動する(赤矢印の流れ)。MBMが基本領域1のブートセクターをチェーンロードすると、その先にはNTLDRがあり、3つのNT系OSを起動する。その他の基本領域にはWindows9x系があり、直接MBMがチェーンロードする。ハードディスクAの拡張領域の拡張PBRをMBMがチェーンロードすると、そこにはLILOがあって、このLILOで4つのLinuxディストリビューションの各カーネルをロードする(黒矢印の流れ)。以上がハードディスクAが第1ハードディスクである場合の起動の流れだ。
この時点でMBMは論理領域起動はできなかったが、現バージョンは可能だ。ただここの説明ではこのままMBMが論理領域起動ができないほうが、若干説明に都合がいいので、そのままにしている。またあとで出てくるWindowsME起動問題も現時点では解決しているのであしからず。
一方ハードディスクBが第1ハードディスクになっている場合、MBRにはやはり「フリーツール編」で紹介するext-IPLというブートローダを配置してある。ext-IPLは論理領域を起動できるので、各基本領域とLinuxの入ったハードディスクAの論理領域3と4、及びハードディスクBの論理領域2と3のブートセクターをチェーンロードする(青矢印の流れ)。各Linux領域のブートセクター(Linuxでは普通スーパーブロックと呼びます)にはそれぞれのカーネルをロードするLILOが配置されており、これらが各カーネルをロードする。
メインのハードディスクAのMBRにMBMを配置してメインのブートローダとして使っている理由はMBMの区画エディタなどの機能の有効性と、MBMのグラフィックメニュー機能が私のお気に入りだからだ。しかしMBMは論理領域起動ができないので拡張PBRにLILOを配置して、Linuxの起動は全般的にLILOに任せる。
またMBMは第2ハードディスク以降からWindowsMEの起動に問題があるため、MBM起動時にはWindowsMEが第1ハードディスクになければならない。だから、ハードディスクBが第1ハードディスクの場合、第2ハードディスク以降のWindowsMEを問題なく起動できるext-IPLをMBRに配置している。ext-IPLは拡張領域起動ができない一方で論理領域起動が可能なので、MBMとは違い、直接それぞれの論理領域のブートセクターをチェーンロードして、そこからカーネルのロードはLILOに引き継ぐ形になる。上図で黄色の部分にはLILOがあることを示している。
つまりこの構成ではLILOは全部で6箇所に存在する。各論理領域のLILOはその領域をルートしているディストリビューションが起動時に作成し、役割は主にそのディストリビューションのカーネルの起動だ。一応他のカーネルもロードできるようにしているがあまり使わない。
またパーティションAの拡張PBRにインストールしたLILOはハードディスクAの論理領域3にインストールしたTurboLinux上で作成するが、目的は全ディストリビューションのカーネルの起動だ。ハードディスクBの拡張PBRにもLILOを一応入れてますが、これは実際は必要ないので、特に説明しない。また各LILOからはWindowsも起動できるようにする。もしからしたらLILOに移った後で、気が変わるかもしれないからだ。
さて、この構成でマルチブート的にポイントとなるのは以下だ。
実際他にもいろいろあるが、このページではマルチブート全般の話はメインではないので、これらの点は機能編や各ブートローダの説明の項に譲るとして、ここではLILOのテクニックについて説明しよう。
上記の構成で使われているLILOのテクニックは以下のようなものだ。
個々の説明に入る前に、まずこの構成を司るLILO達を作成する設定ファイル/etc/lilo.confを見てみよう。まずはハードディスクAの拡張PBRに置かれるメインのLILOの場合だ。このLILOはMBRにあるMBMからチェーンロードされて、全てのディストリビューションのロードを司る。因みにハードディスクAはUltraATA66カードのプライマリマスターに接続されているため、デバイススペシャルファイル名は「/dev/hde」となる。ハードディスクBはノーマルのIDEのプライマリマスターなので「/dev/hda」だ。
[1. ハードディスクAの拡張PBRに置くLILOのためのTurboLinux上のlilo.conf]
boot=/dev/hde3 map=/boot/map prompt timeout=1000 lba32 keytable = /boot/jp106.ktl menu-title="Turbo Menu EPBR" menu-scheme=Cb:kc:Gb:Yb disk=/dev/hde bios=0x80 disk=/dev/hda bios=0x81 image=/boot/vmlinuz label="Turbo Linux 6.0" root=/dev/hde7 initrd=/boot/initrd read-only image=/mnt/debian/boot/vmlinuz label="Debian" root=/dev/hde8 initrd=/mnt/debian/boot/initrd read-only image=/mnt/redhat/boot/vmlinuz-2.2.14-5.0 label="Red Hat 6.2J" root=/dev/hda6 initrd=/mnt/redhat/boot/initrd-2.2.14-5.0.img read-only image=/mnt/slack/vmlinuz label="Slackware 7.1" root=/dev/hda7 read-only other=/dev/hde1 label="Windows2000" table=/dev/hde change partition=/dev/hde1 activate partition=/dev/hde2 deactivate other=/dev/hde2 label="WindowsME" table=/dev/hde change partition=/dev/hde1 deactivate partition=/dev/hde2 activate other=/dev/hda1 label="Windows98" table=/dev/hda change partition=/dev/hda1 activate partition=/dev/hda2 deactivate map-drive=0x80 to=0x81 map-drive=0x81 to=0x80 other=/dev/hda2 label="Windows95" table=/dev/hda change partition=/dev/hda1 deactivate partition=/dev/hda2 activate map-drive=0x80 to=0x81 map-drive=0x81 to=0x80 |
注目してほしいのは赤色の部分と青色の部分だ。赤色の部分はLILO全般、またはLinuxカーネル起動における注目点で、青色の部分はWindows系OS起動時に重要となる設定部分である。それぞれの説明は後ほど行うが、ポイントはこのLILOはハードディスクAが第1ハードディスクである場合にだけ、実行されるということである。
次にハードディスクBの論理領域2のブートセクターに置かれ、Redhat上から作成されるLILOのための設定ファイルの例だ。色分けの意味は1番と同じである。1番と何が違うかを見て、その違いがどこから来るものなのかを理解をしてほしい。
[2. ハードディスクBの論理領域2に置くLILOのためのRedhat上のlilo.conf]
boot=/dev/hda6 map=/boot/map prompt timeout=700 lba32 keytable = /boot/jp106.ktl menu-title="Redhat Menu" disk=/dev/hde bios=0x81 disk=/dev/hda bios=0x80 image=/boot/vmlinuz-2.2.14-5.0 label="Red Hat 6.2J" root=/dev/hda6 initrd=/boot/initrd-2.2.14-5.0.img read-only image=/mnt/slack/vmlinuz label="Slackware 7.1" root=/dev/hda7 read-only image=/mnt/turbo/boot/vmlinuz label="Turbo Linux 6.0" root=/dev/hde7 initrd=/mnt/turbo/boot/initrd read-only image=/mnt/debian/boot/vmlinuz label="Debian" root=/dev/hde8 initrd=/mnt/debian/boot/initrd read-only other=/dev/hde1 label="Windows2000" table=/dev/hde change partition=/dev/hde1 activate partition=/dev/hde2 deactivate map-drive=0x80 to=0x81 map-drive=0x81 to=0x80 other=/dev/hde2 label="WindowsME" table=/dev/hde change partition=/dev/hde1 deactivate partition=/dev/hde2 activate map-drive=0x80 to=0x81 map-drive=0x81 to=0x80 other=/dev/hda1 label="Windows98" table=/dev/hda change partition=/dev/hda1 activate partition=/dev/hda2 deactivate other=/dev/hda2 label="Windows95" table=/dev/hda change partition=/dev/hda1 deactivate partition=/dev/hda2 activate |
この設定ファイルの場合もポイントとなるのはこちらはハードディスクBが第1ハードディスクである場合にのみ実行されるということである。
最後にハードディスクAの論理領域3のブートセクターに置かれるLILOをTurboLinux上から作成する場合の設定ファイルの例だ。
[3. ハードディスクAの論理領域3に置くLILOのためのTurboLinux上のlilo.conf]
boot=/dev/hde7 map=/boot/map7 prompt timeout=500 lba32 keytable = /boot/jp106.ktl menu-title="Turbo Menu" menu-scheme=Cb:kc:Gb:Yb
disk=/dev/hde
|
TurboLinux上で作成するのに記述は1番のものではなく、2番のRedhat上で作成する場合の設定ファイルの方に近い理由も考えてほしい。やはりポイントはこのLILOがハードディスクBが第1ハードディスクだった場合にのみ実行されることである。また1番と3番はいずれもTurboLinux上で作成される。同じマップインストーラで2つのLILOを作る必要があるのだが、その場合の注意点も確認してほしい。
上記のほかにハードディスクAの論理領域4のdebian上のLILOや、ハードディスクBの論理領域3のSlackware上のLILOもあるが、それぞれ3番、2番と似ているので省略する。
このページを読み終わればあなたもこのような設定ファイルを記述してLILOを作成し、同様の構成を自分で作成することができるようになるはずだ。それがこのページの目的である。
Linuxには数多くのディストリビューションがあるので一つのPCに、あるいは一つのハードディスクに複数のディストリビューションをインストールしたいと思う場面も多いだろう。そのような場合、それぞれのディストリビューションをどのように起動しようと考えるだろうか。結局これは複数のOSをインストールするのと同じことになる。
一つにはそれぞれのOSを別の基本領域にインストールし、LILOをそれぞれのルートパーティションに置いて、MBRに別途ブートローダを用意して、2つのLILOを起動し分けるかもしれない。今、あるIDEハードディスクの第1基本領域にTurboLinuxを第2基本領域にRedhatをインストールし、それぞれのLILOをそれぞれの基本領域の先頭セクターにインストールして、MBRにMBMなどのブートローダを置いてLILOを起動する場合を考えてみる。以下にその場合のそれぞれのOSでのlilo.confを示す。
[TurboLinuxのlilo.conf]
boot = /dev/hda1 map = /boot/map prompt timeout = 100 image = /boot/vmlinuz label = turbo root = /dev/hda1 |
[Redhatのlilo.conf]
boot = /dev/hda2 map = /boot/map prompt timeout = 100 image = /boot/vmlinuz label = redhat root = /dev/hda2 |
これで2つのOSを起動し分けることができるのだが、これではブートローダが2段構成になってしまう。別のブートローダを使わず、LILOだけで両方のOSをダイレクトに起動するようにすることはできないのだろうか? 勿論可能だ。その時には当然LILOのインストール先を/dev/hdaにする、つまりIDEハードディスクのMBRにインストールするなどの変更が必要で、更に一つのLILOから両方をダイレクトに起動するのだから、上記のlilo.confを統合する必要がある。以下にTurboLinux側のlilo.confに統合した場合を示す。
[TurboLinuxとRedhatを統合したlilo.conf]
boot = /dev/hda map = /boot/map prompt timeout = 100 image = /boot/vmlinuz label = turbo root = /dev/hda1 image = /boot/vmlinuz label = redhat root = /dev/hda2 |
さて、これだけでいいのだろうか? 実はこれでも、まだだめなのである。問題はRedhat側だが、見ての通りカーネルイメージがTurboLinuxと同じものを指してしまっている。従ってこのままではTurboLinuxのカーネルが起動して、ルートを第2基本領域にするという変則的な起動をしてしまうのだ。まあ上記例ではたまたま同じものだったのだが、もし同じでなかったらエラーになるのが普通だろう。Redhat側のカーネルはTurboLinux側からみたら/boot/vmlinuzではないのである。
ちゃんとRedhat側はRedhatのカーネルが起動されるようにしなければいけない。それにはTurboLinuxが起動している状態でもRedhat側のカーネルが見えるようにしておき、そのTurboLinuxから見える形で指定しなければいけない。たとえばRedhat側のルートパーティションである第2基本領域をTurboLinuxでは「/mnt/redhat」にマウントしてみる。その上で以下のようにlilo.confを変更する。
[Redhatカーネルを起動できる正しいlilo.conf]
boot = /dev/hda map = /boot/map prompt timeout = 100 image = /boot/vmlinuz label = turbo root = /dev/hda1 image = /mnt/redhat/boot/vmlinuz label = redhat root = /dev/hda2 |
これでRedhatが、本来の自分のカーネルで起動される。この例ではTurboLinux側に統合してみたが、これをRedhat側に統合した場合でも同じだ。その場合、TurboLinuxの第1基本領域をRedhat側でどこかにマウントして、TurboLinuxのカーネルを明示的に指定する必要がある訳である。
またこのことはカーネルに限った話ではないことも記憶しておいて頂きたいと思う。結局lilo.confに指定する各データはカーネルに限らず、マップインストーラ(liloコマンド)を実行する時点で見える形で指定する必要があるということだ。
Linuxをいじり倒していて、起動時にLILOが『LI』とだけ表示して、止まってしまうのを経験したことのない人は非常に少ないのではないだろうか? 最もよく起こるLILOのトラブルの一つだ。また上記の他に「L」だけで止まったり、「LIL-」や「LIL?」となってしまうことも含めると、これらを経験したことのない人は皆無に近いのではないだろうか? 一体このトラブルは何なのだろうか。これを説明するにはLILO起動時の表示「LILO」の意味を説明する必要がある。また根本原因であるところのLILOの絶対番地依存の性質も説明する必要があるだろう。
LILO起動時に表示される「LILO」という文字列はどこかのロジックで一度に表示している訳ではなく、実はいくつかのロジックが進むごとに1文字ずつ表示している。従ってこの表示状況によって、どこでエラーが起きて止まっているのかがある程度推測することができる。以下にそれぞれの文字を表示するステージを示す。
詳細は「ブートローダメッセージ」を参照して欲しいのだが、ここでは今回の主題である最も典型的な『LI』で止まる場合を詳しく説明する。上記を見ると「LI」だけで止まるということは2番目の「L」が表示できない訳だから、LILOの1st Boot Loaderが、2nd Boot Loaderをロードは出来たが、その実行が開始できないのだ、ということが分かると思う。
上図で言うと、1st BLが2nd BLを見つけてメモリにロードし、実行制御を移したのだが、正しく実行されなかったというものだ。なぜ実行に失敗するのかと言えば、そもそも2nd Boot Loaderのロードに成功したと言っても、実際は正しく(正しいものが)ロードされていない場合が殆どである。
2nd Boot Loaderの実体は通常「/boot/boot.b」というファイルだ(厳密にはこのファイルの一部だ)。マップインストーラ実行時に1st Boot Loaderの内部にこの2nd Boot Loaderの位置がハードディスクディスク上の絶対番地で記録される。1st Boot Loaderは実行時に自分の内部に記録された2nd Boot Loaderの絶対番地を頼りに2nd Boot Loaderをロードする(正確にはその絶対番地をBIOSに示してロードしてもらう)。
しかし、何らかの理由で2nd Boot Loaderが無くなってしまうか、移動させられると、その絶対番地には別のものがあるか、または何のデータもないかもしれない。1st Boot Loaderはそのデータが実際は2nd Boot Loaderで無かろうが、なんであろうが、お構いなしにメモリにロードして、自分のすべきことは終わったとして、「I」と表示する。そして1st Boot Loaderが2nd Boot Loaderだと思っているそのデータに制御を移し、実行する段になって続行不能になり、停止することになる訳だ。
このように、1st Boot Loaderが2nd Boot Loaderがあると思ってロードした場所に実際には2nd Boot Loaderが無かったというのは一体どういう時に起こるのだろうか。それは非常にいろいろな場面があると思うが、いくつか典型な例を挙げ、その対処法にも触れてみたいと思う。
まずはLinuxの単独インストールの時は勿論、Windowsとのマルチブートの場合でも、LILOをメインのブートローダとして利用している場合、LILOをMBRにインストールすることが多いだろう。このシチュエーションでは1st Boot LoaderがMBRにあり、2nd Boot LoaderはLinuxルートパーティションにあるということになる。つまり距離的には結構離れて存在する訳だね。こういう場合に、Windowsだけの単独ブートに戻したい場合や、新たにWindows NT/2000をインストールするために、Linuxのパーティションを削除したり、再フォーマットなどすると2nd boot loaderが無くなってしまい、この障害が起こることになる。まあ当たり前といえば当たり前だが。
新たにインストールするOSが、Windows9x/MEやWindows XPの場合はインストーラがMBRに強制的にIBMブートストラップローダを書き込むので、LILOは1st boot loaderを含め、跡形もなく消え去るためこの問題は起きない。しかしWindows NT/2000のインストーラは行儀がいいのか、気が利かないのか、意見が分かれるところだが、MBRに一切触れないので、この「LI」停止問題に直面することになる。
この場合の対処法としてはやはり一人MBRに取り残された形になった1st boot loaderを削除する(正確にはMBRをIBMオリジナルのブートストラップローダに戻す)他ないだろう。方法はこのサイトでもいろいろな所で言及してきたが、DOSやWindows9xの起動ディスクで起動して「fdisk /mbr」コマンドを実行するか、Windows2000の回復コンソールで「fixmbr」コマンドを実行してほしい。
次に、上記のように完全に2nd boot loaderが無くなってしまったという場合ではなくても、たとえば少しでも「/boot/boot.b」を移動したら、たちまち同現象が起こる。それは「/boot/boot.b」を「/root/boot.b」へ移動したとかではなく、単に別のところへ移して、また「/boot/boot.b」に戻しても、物理的なハードディスク上の絶対番地など保証などされないのだから、やはり絶対番地不一致が起きて「LI」で止まる。
ただ「/boot/boot.b」などLILOを構成するファイルは実際はあまり更新することもないだろうし、更新時はマップインストーラを実行するので、普通の使い方をしているぶんには更新による絶対番地の不一致は起き難いはずである。
それよりも多いと思われるのがハードディスクの構成変更による絶対番地の変更だ。例えば以下のlilo.confを見てほしい。
boot = /dev/hda map = /boot/map prompt timeout = 100 image = /boot/vmlinuz label = linux root = /dev/hdc1 other = /dev/hda1 label = windows table = /dev/hda |
この設定ファイルを見てLILOを構成する各データがどこに配置されているか、読み取れる人はどれくらいいるだろうか。もっとも/etc/fstabなども見てみないと正確なところは分からないが、次のような構成を想像できると思う。
プライマリマスター(/dev/hda)に繋がったハードディスクに少なくとも一つの基本領域があって、ここにWindowsがインストールされている。セカンダリマスター(/dev/hdc)に繋がったハードディスクに少なくとも一つの基本領域があって、そこにLinuxがインストールされている。LILOの1st Boot LoaderはプライマリマスターのHDDのMBRにある。たぶんLinuxデータはすべてセカンダリマスターのHDDにあると思われるので、LILOのその他のデータ(2nd Boot Loaderやマップファイルなど)やカーネルなども皆このハードディスク上にある。
さて、ここで上記2つのハードディスクは全く触れることもなく、単にプライマリスレーブ(/dev/hdb)にハードディスクを一つ増設したとしよう。関係のないディスクの増設に過ぎないから、何事もないと期待するかもしれない。ところがどっこい、忽ち「LI」でLILOが止まって起動不能に陥る。これはハードディスクの絶対番地にはハードディスクの番号も含まれており、この番号がハードディスクの増設によってずれてしまったからだ。
LILOはBIOSに依頼してハードディスクからデータを読むため、BIOSが認識できるようなハードディスクの管理しかできない。BIOSではハードディスクをプライマリマスターとかセカンダリスレーブとかの接続場所を正確に管理しているのではなく、単に見つけた順に番号を振った連番で管理しているだけである。
たとえば上記設定ファイル例では/dev/hdaが第1ハードディスク、/dev/hdcが第2ハードディスクとして、LILOの各データには記録されている。この時点ではBIOSも同様の認識なので問題ない。ところが/dev/hdbが増設されるとBIOSから見るとこちらが第2ハードディスクとなり、/dev/hdcが第3ハードディスクになってしまう。
このままLILOを更新せずに実行すると、まだLILOはデータが第2ハードディスクにあると思っているから、BIOSとLILOで認識の食い違いが起こる訳だ。BIOSに依頼してデータを読む以上、この認識の齟齬は致命的である。例では2nd Boot Loaderも/dev/hdcにあると思われるので、/dev/hdaにある1st Boot Loaderが、もはや第3ハードディスクになってしまった/dev/hdcにある2nd Boot Loaderをロードできず(BIOSには第2ハードディスクのデータの読み込みを依頼するので、増設したハードディスクの方を読みに行って、ロードできたと思っている)、そちらに制御を移しても正常に実行されず「LI」で止まる訳だ。
一応この問題はあらためてマップインストーラを実行し、LILOの各データに「/dev/hdcは第3ハードディスク」であるとして記録しなおせば解決する。まあ大抵はこのようにマップインストーラの再実行で治るものが多いのだが、起動しないと再実行も当然できない訳で、やはりLILOの絶対番地依存の性質は大きな欠点と言わざるをえない。ブートディスクを手放すことができない訳である。
更に上記例はマップインストーラの再実行で回避できる訳だが、単なる再実行では回避できない問題もある。それについては次項で説明する。
因みにGRUBはこの絶対番地依存の度合いが非常に低いので、各データの変更に対して非常に柔軟だ。また絶対番地依存の部分も起動時に変更して起動するといったことが可能なので、殆ど起動不能になることはない。
LILOはBIOSにハードディスクのデータの読み込みを依頼するため、BIOSと同様のハードディスク管理しかできないと説明した。これは実際は大きな問題ではない。少なくともLILOに限定された問題ではない。すべてのブートローダが抱えている問題である。
問題なのはLILOがハードディスクの順序を決めるにあたってBIOSと相談している訳でもなく、デバイススペシャルファイル名(/dev/hdaとかいう名称)を見て、勝手にハードディスクの順序を決めてしまっていることだ。従って、少しでもイレギュラーな順序にしているとうまく動作しない。例えば/dev/hdaは第1ハードディスクで、/dev/hdbが第2ハードディスクと決めてしまっている。だから何らかの事情で、/dev/hdbを第1ハードディスクにしている場合、不都合が生じる。
以下にIDEハードディスクを考えられる全てのパターンで接続させて、LILOが認識するハードディスクの順序(ドライブID)を調べてみた。ドライブIDが0x80が第1ハードディスク、0x81が第2ハードディスクなどとなる。因みにBIOS(実験環境はASUS P2L97 AWARD BIOS 1010だ)ではPrimary-Mastor、Primary-Slave、Secondary-Mastor、Secondary-Slaveの順序で(これは不動)、接続されているものだけ、0x80から順にIDが振られます。
[LILOが認識するドライブID]
Primary-Mastor |
Primary-Slave |
Secondary-Mastor |
Secondary-Slave /dev/hdd |
|
1 | 0x80 | - | - | - |
2 | - | 0x81 | - | - |
3 | - | - | 0x80 | - |
4 | - | - | - | 0x81 |
5 | 0x80 | 0x81 | - | - |
6 | 0x80 | - | 0x81 | - |
7 | 0x80 | - | - | 0x82 |
8 | - | 0x81 | 0x80 | - |
9 | - | 0x81 | - | 0x81 |
10 | - | - | 0x80 | 0x81 |
11 | 0x80 | 0x81 | 0x82 | - |
12 | 0x80 | 0x81 | - | 0x83 |
13 | 0x80 | - | 0x81 | 0x82 |
14 | 0x81 | 0x80 | 0x81 | |
15 | 0x80 | 0x81 | 0x82 | 0x83 |
太字がBIOSの認識と一致しているものだ。特徴としてはスレーブに接続したハードディスクは決して第1ハードディスクにならないね。結局全てのハードディスクに対してBIOSの認識と一致するパターンは1番、3番、5番、6番、10番、11番、13番、15番ということになる。それ以外(2番、4番、7番、8番、9番、12番、14番)はBIOSとLILOで認識が一致しない。
またLILOはSCSIハードディスクは常にIDEより後だと決めてかかっている。最近はPC/AT互換機でもBIOSの設定でブートシーケンスを変更できるようになっているので、IDE、SCSI混在環境で、SCSIを先に設定した場合なども、当然LILOの認識とBIOSの認識する実際のハードディスクの順序に食い違が生じる。
LILOとBIOSの認識に食い違いがLILOの動作不能の原因になることは前項で説明した。またこれはマップインストーラが上記のような動作をするのだから、このままでは何度マップインストーラを実行し直しても、一向に改善はされない。
これを回避するために、LILO(マップインストーラ)に明示的に、このハードディスクが第1ハードディスクで、あっちの方が第2ハードディスクであるなど、BIOSが認識する順序(ドライブID)を教えてあげる必要がある。
これはグローバルセクションの「disk」オプションと「bios」サブオプションで指定する。「disk」オプションにはハードディスクのデバイス名を、「bios」サブオプションには第1ハードディスクなら「0x80」を第2ハードディスクなら「0x81」を指定する。
[BIOSから見たハードディスクの順序の設定]
boot = /dev/fd0 prompt timeout = 100 disk = /dev/sda bios = 0x80 disk = /dev/hda bios = 0x81 image = boot/vmlinuz label = lin root = /dev/hda4 other = /dev/hda1 label = win95 ・ ・ |
これでBIOSとの認識の違いは是正することができる。
あるOSを起動している状態で、マップインストーラ(liloコマンド)でLILOを作った後で、設定ファイルを書き換えて、またマップインストーラを実行した場合、前の設定ファイルのLILOはどうなるだろうか?
基本的には無効になる。ではたとえばインストール先をフロッピーにしたものとMBRにしたものを2つ作り、いずれも有効に利用することは同じOS上の同じマップインストーラからではできないのだろうか? 実はこのように使い分けをするために、インストール先を分けて複数のLILOを同じマップインストーラから作成することは可能である。
本来この説明をするにはLILOのデータ構造を解説する必要があるのだが、その解説抜きに掻い摘んで説明する。インストール先は「boot」文で記述する訳だが、あとは「install」文で記述するマップファイルを別のものにするだけで問題なく、使い分けができる。つまり競合を避けなければいけないはマップファイルだけだということである。まあ簡単だね。
[フロッピーにLILOをインストールするための設定ファイル]
boot = /dev/fd0 install = /boot/fdmap |
[ルートにLILOをインストールするための設定ファイル]
boot = /dev/hda2 install = /boot/rootmap |
[MBRにLILOをインストールするための設定ファイル]
boot = /dev/hda install = /boot/mbrmap |
このようにしておけば、それぞれ有効なLILOとして問題なく動作する。因みに「install」文は省略するとデフォルトで「/boot/map」が使用されるので注意してほしい。
Linuxの場合、アクティブでない基本領域からでもたとえ論理領域でも、また第2ハードディスク以降からでも基本的に問題なく起動することができる。Linuxはインストール位置に対して非常に柔軟なOSだ。
しかしこれはあくまで最初からそこにLinuxをインストールした場合の話で最初に第1ハードディスクにインストールしたものを後から第2ハードディスクにする場合は問題である。インストール後に変更した場合は前述したようにLILOの絶対番地依存の性質によって、たちまち起動不能に陥る。
ただしこれも前述したようにブートディスクなら起動できるから、これで起動してLILOを作り直せば大丈夫だ。またやはり前述のようにGRUBで起動してもいいだろう。
しかしこれもハードディスクの接続は変えずに単にBIOSの設定などでBIOSからみたハードディスクの順序を変えただけ場合の話に過ぎない。例えばIDEのプライマリーマスターに接続していたものをプライマリースレーブやセカンダリマスターに変更するといった接続方法そのものを変える場合は実は話が簡単ではない。
何度か述べているようにLinuxの場合、例えばIDEのプライマリーマスターは「/dev/hda」というデバイス(スペシャル)ファイル名で表現される。プライマリスレーブは「/dev/hdb」になる。ハードディスクの接続を変えた場合、このデバイスファイル名が変わることになる。
カーネルが存在する位置のデバイスファイル名が変わると、たとえブートディスクでも起動できなくなる。これはブートディスクにカーネルの位置としてデバイスファイル名で記録されてしまっているからだ。
ただしGRUBを利用すればカーネルのロードは行うことはできる。これはGRUBは起動時に起動方法を柔軟に変更できたり、現在は存在しないブートエントリを作成しておくことも可能だからだ。起動時にGRUB Shellで手動で変わってしまったカーネルの位置を指定したりとか、予めエントリを作っておいてデバイスファイル名が変わった場合に備えておけばいいだろう。
しかしこれでもまだ問題がある。GRUBで首尾よくカーネルがロードできても、その後のLinuxの起動プロセスの中でファイルシステムのマウントに失敗してしまうのだ。これはマウントするパーティションがデバイスファイル名でベタ書きされたデータがあるからである。それは「/etc/fstab」ファイルだ。
幸い通常デバイスファイル名がベタ書きされたデータはこの「/etc/fstab」ひとつだけだ。ではこれを書き換えてしまえばいいのはないだろうか。しかし問題はまだ残る(結構しつこい)。これをどのタイミングで書き換えるかである。結論から述べるといくつかの方法があり可能だ。
しかしとても危険なので、万が一の場合に備え、レスキューディスク(ブートディスクではないだよ)は用意してほしい。それもちゃんとハードディスクの/etc/fstabを編集できるようにviなどのエディタが使えるレスキューディスクだ。別にレスキューディスクでなくても構いない。要は起動しなくなってしまったLinux上のデータを編集できる方法を用意しておけばいいのである。たとえば1FD Linuxを用意するとか、別のハードディスクから起動できるLinuxを用意しておいてもいいだろう。手段は問わない。この方法が用意できない人は危険なのでやらないでほしい。
またGRUBが使えないといけないので、「GRUB」の全体構造をよく理解し、更に「GRUBの詳細」を熟読してGRUB Shellが使えるようにする必要がある。決して難しくないが、非常に簡単という訳でもない。GRUB Shellは必ずしも必要ないのだが、失敗時の対応のために是非ともマスターしておいてもらいたい。
具体的に、最初にプライマリマスター(/dev/hda)にインストールしたものをプライマリスレーブ(/dev/hdb)に移してLinuxを起動する場合を例にとって説明しよう。カーネルのある/bootが第1基本領域(/dev/hda1)、ルートが第1論理領域(/dev/hda5)、swapが第2論理領域(/dev/hda6)ということにしよう。
手順は以上になる。それぞれをもう少し詳しく説明しよう。
まずGRUBのブートディスクだが、「GRUBの詳細」を参考にして作ってほしい。メニューから起動できるようにmenu.lstも作った方がいいだろう。例えば以下のようなmenu.lstになるはずである。
[設定ファイル「/boot/grub/menu.lst」の記述例]
timeout 30 default 0 title Turbo Linux 6.0 Workstation kernel (hd0,0)/vmlinuz root=/dev/hda5 initrd (hd0,0)/initrd |
さらに予めプライマリスレーブに接続した時のためのエントリも作っておこう。正しく作っておけばGRUB Shellを使う必要がなくなる。
[環境変更後のエントリも加えたmenu.lstの記述例]
timeout 30 default 0 title Turbo Linux 6.0 Workstation hda kernel (hd0,0)/vmlinuz root=/dev/hda5 initrd (hd0,0)/initrd title Turbo Linux 6.0 Workstation hdb kernel (hd1,0)/vmlinuz root=/dev/hdb5 initrd (hd1,0)/initrd |
(hd1,0)の部分はもし接続を変えるだけで、プライマリマスターに何か別のディスクを接続する訳ではないのなら、ハードディスクのBIOSから見た順序は変わらないので、元のままでいい。もっともプライマリマスターに別のディスクを接続する予定がないのにプライマリスレーブに接続替えすることは普通ないだろうが。
次に移行前の状態でLinuxを起動し、/etc/fstabを書き換える。何しろ書き換えたら今度は現環境では起動しなくなるのでここは慎重にやりたいところだ。間違えて現環境も新環境も起動できないようなものに書き換えてしまったら、前述のようにレスキューディスクなどのお世話になることになる。
例の場合、元の/etc/fstabは以下のようなイメージだと思う。
[/etc/fstabの記述例]
/dev/hda1 /boot ext2 defaults
1 1 /dev/hda5 / ext2 defaults 1 1 /dev/cdrom /mnt/cdrom iso9660 noauto,owner,ro 0 0 /dev/fd0 /mnt/floppy auto noauto,owner,ro 0 0 none /proc proc defaults 0 0 none /dev/pts devpts gid=5,mode=620 0 0 /dev/hda6 swap swap defaults 0 0 |
これをプライマリスレーブ(/dev/hdb)用に書き換えると以下のようになるだろう。
[変更後の/etc/fstab]
/dev/hdb1 /boot ext2
defaults 1 1 /dev/hdb5 / ext2 defaults 1 1 /dev/cdrom /mnt/cdrom iso9660 noauto,owner,ro 0 0 /dev/fd0 /mnt/floppy auto noauto,owner,ro 0 0 none /proc proc defaults 0 0 none /dev/pts devpts gid=5,mode=620 0 0 /dev/hdb6 swap swap defaults 0 0 |
まあ、hdaとなっている部分をhdbに変えるだけなのでまず間違えることはないだろう。このように変更すると今度はもはやプライマリマスター接続では起動できなくなる。
後はシャットダウンして、繋ぎ変えて起動だね。起動はGRUBブートディスクで行い、予め作っておいたhdb用のエントリから起動する。
以上でうまくプライマリースレーブに引越したTurboLinuxが起動したはずである。起動後は新環境用にLILOを作成しなおしてもいいし、そのままGRUBディスクで起動してもいいし、GRUBを正式にハードディスクに導入してもいいだろう。
MicrosoftのOSは第2ハードディスク以降からの起動は何かと問題がある。そもそも普通は第2ハードディスク以降にインストールすることはできない。一旦第1ハードディスクにインストールして、接続替えするということになる。この問題については「機能編」を参照してほしい。
ただし前述のLinuxの場合のように接続位置を保持しているデータはないので、インストール後の接続替えは逆に楽だ。もっとも最初から第2ハードディスク以降にインストールできないので、接続替えができなかったら万事休すである。
MicrosoftのOSを第2ハードディスク以降から起動するには「機能編」でも説明しているように、いくつか方法があるようだが、LILOの場合は最も一般的なドライブスワップ方式を採用している。これは第2ハードディスク以降と第1ハードディスクをBIOSレベルで入れ替えてしまってOSを騙してしまう方法である。
それは「map-drive」オプションと「to」サブオプションで指定する。「map-drive」オプションには元のデバイスのBIOSが認識する順序(1番なら0x80)、「to」サブオプションにはそのパーティションが存在する本当のハードディスクのBIOSが認識する順序(2番なら0x81)を指定する。入れ替え(スワップ)なので、逆(0x81から0x80)も合わせて指定しておかないと正しく動作しない。
[ドライブスワップの設定]
boot = /dev/hda prompt timeout = 100 image = boot/vmlinuz label = lin root = /dev/hda4 other = /dev/hdb1 label = win95 map-drive = 0x80 to = 0x081 map-drive = 0x81 to = 0x080 table = /dev/hdb other = /dev/hdb2 label = winnt map-drive = 0x80 to = 0x081 map-drive = 0x81 to = 0x080 table = /dev/hdb ・ ・ |
これで第2ハードディスクにあるMicrosoft系のOSの起動も多少は可能になる。しかしそもそも第2ハードディスクからの起動を想定して作られたOSではないので、まくいかない場合もある。
たとえばWindows9xは第2ハードディスクだった場合、先頭のパーティションでないとうまく起動しないことがある。このあたりの事情はLILO側ではどうしようもない。どんなブートローダを使っても同じことだ。あまりWindows系OSの第2ハードディスク以降からの起動に関し、多大な期待はしないほうがいいだろう。
複数のWindows系OSとマルチブートを行っていく場合、どうしても必要になるのがアクティブ属性の切り替え機能である。このことについての内容的な詳細は「機能編」を参照してほしい。
LILOにはちゃんと特定のOSを起動した場合、特定のパーティションをアクティブにしたり、別のパーティションを非アクティブにしたりする機能が用意されている。「change」オプションとその「partition」サブオプションと更にその「activate」サブオプション(アクティブ化)、「deactivate」サブオプション(非アクティブ化)を使う。
[アクティブ属性の切り替え]
boot = /dev/hda prompt timeout = 100 image = boot/vmlinuz label = lin root = /dev/hda4 other = /dev/hda1 label = win95 change partition = /dev/hda1 activate partition = /dev/hda2 deactivate partition = /dev/hda3 deactivate table = /dev/hda other = /dev/hda2 label = winnt change partition = /dev/hda1 deactivate partition = /dev/hda2 activate partition = /dev/hda3 deactivate table = /dev/hda other = /dev/hda3 label = win98 change partition = /dev/hda1 deactivate partition = /dev/hda2 deactivate partition = /dev/hda3 activate table = /dev/hda |
図の例ではLinuxの他、Windows95とWindowsNTとWindows98がそれぞれ別の基本領域にインストールされており、LILOによってマルチブートを行う場合を示している。またWindows系OSはそれぞれ、自分が起動されると自分の領域をアクティブにするとともに、他のWindows系OSがインストールされているパーティションを非アクティブ化している。
因みにこの「change」オプションはそのサブオプションとともに、「other」セクション(つまりLinux以外のOSのセクション)にしか指定できない。「image」セクション(Linuxのセクション)に指定するとエラーになる。つまりLinuxを起動するときには他のパーティションのアクティブ属性を変更できないのだ。これはLinuxは別に他のパーティションのアクティブ属性がどうなっていようと起動に何の支障もないので、その必要がないからだろう。もっともLinux起動時にも他のパーティションのアクティブ属性を変更したいという要望は皆無ではないので、用意してほしかったね。
ところで「change」オプションはパーティションテーブルの情報を書き換えるオプションなので、一応危険視されており、LILOコマンドのデフォルトでは利用できないことになっている(少なくともReadmeにはそう書いてある)。この機能を利用するには「REWRITE_TABLE」環境変数を定義して、LILOコマンドをmakeし直す必要がある。
もっともLILO Ver21のmakefileはデフォルトで上記環境変数が定義されていた。最近のディストリビューションに入っているLILOなら、最初から利用できるものが多いようだ。もし利用できないようなら自分でmakeし直してほしい。
最初の私が構築した設定ファイル例にはなかったが、Windows系OSのマルチブートにおいて、アクティブ属性の変更とともに重要なのが隠しパーティションである。このことについての内容的な詳細も、「機能編」を参照してほしい。
やはり「change」オプションの孫サブオプションに「set」サブオプションがあり、設定するパーティションタイプを指定する。ただし多くのパーティションタイプはデフォルトでは未定義なので、あらかじめグローバルオプションの「change-rules」オプションで定義しておく必要がある。
「type」サブオプションで、パーティションタイプ名を定義し、「normal」サブオプションで通常の値を指定し、「hidden」サブオプションで隠しパーティション時の値を指定する。値の指定は16進数でも10進数でもかまいないが、こういう値は習慣的に16進数だろう。
[パーティションタイプの定義]
boot = /dev/hda prompt timeout = 100 change-rules type = fat32 normal = 0x0b hidden = 0x1b type = ntfs normal = 0x07 hidden = 0x17 image = boot/vmlinuz label = lin root = /dev/hda4 other = /dev/hda1 label = win95 ・ ・ |
パーティションタイプの中で、FAT12、FAT16(Small)、及びFAT16(Big)の3つだけは既に以下のように定義されている。
type = DOS12
normal = 0x01
hidden = 0x11
type = DOS16_Small
normal = 0x04
hidden = 0x14
type = DOS16_Big
normal = 0x06
hidden = 0x16
そして各otherセクションの「change」オプションの「parttition」サブオプションのサブオプションとして「set」オプションで、そのOSを起動した時に、どのパーティションをどういうパーティションタイプに設定するかを記述する。
値は定義したパーティションタイプ名_{normalまたはhidden}という形式になる。
[隠しパーティションの設定]
boot = /dev/hda prompt timeout = 100 change-rules type = fat32 normal = 0x0b hidden = 0x1b type = ntfs normal = 0x07 hidden = 0x17 image = boot/vmlinuz label = lin root = /dev/hda4 other = /dev/hda1 label = win95 change partition = /dev/hda1 activate set = DOS16_big_normal partition = /dev/hda2 deactivate set = ntfs_hidden partition = /dev/hda3 deactivate set = fat32_hidden table = /dev/hda other = /dev/hda2 label = winnt change partition = /dev/hda1 deactivate set = DOS16_big_hidden partition = /dev/hda2 activate set = ntfs_normal partition = /dev/hda3 deactivate set = fat32_hidden table = /dev/hda other = /dev/hda3 label = win98 change partition = /dev/hda1 deactivate set = DOS16_big_hidden partition = /dev/hda2 deactivate set = ntfs_hidden partition = /dev/hda3 activate set = fat32_normal table = /dev/hda |
例ではたとえば、/dev/hda2のWindowsNTを起動した場合、同パーティションは通常のNTFSに設定され、Windows95とWindows98のパーティションはそれぞれFAT16、FAT32の隠しパーティションに設定されている。これだけきめ細かい設定は市販ツールでもできないものが多い。